1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60 package com.jguild.jrpm.io.bzip2;
61
62 import java.io.IOException;
63 import java.io.InputStream;
64
65 /***
66 * An input stream that decompresses from the BZip2 format (without the file
67 * header chars) to be read as any other stream.
68 *
69 * @author <a href="mailto:keiron@aftexsw.com">Keiron Liddle</a>
70 */
71 public class CBZip2InputStream extends InputStream implements BZip2Constants {
72 private static final int START_BLOCK_STATE = 1;
73
74 private static final int RAND_PART_A_STATE = 2;
75
76 private static final int RAND_PART_B_STATE = 3;
77
78 private static final int RAND_PART_C_STATE = 4;
79
80 private static final int NO_RAND_PART_A_STATE = 5;
81
82 private static final int NO_RAND_PART_B_STATE = 6;
83
84 private static final int NO_RAND_PART_C_STATE = 7;
85
86 private CRC m_crc = new CRC();
87
88 private boolean[] m_inUse = new boolean[256];
89
90 private char[] m_seqToUnseq = new char[256];
91
92 private char[] m_unseqToSeq = new char[256];
93
94 private char[] m_selector = new char[MAX_SELECTORS];
95
96 private char[] m_selectorMtf = new char[MAX_SELECTORS];
97
98
99
100
101 private int[] m_unzftab = new int[256];
102
103 private int[][] m_limit = new int[N_GROUPS][MAX_ALPHA_SIZE];
104
105 private int[][] m_base = new int[N_GROUPS][MAX_ALPHA_SIZE];
106
107 private int[][] m_perm = new int[N_GROUPS][MAX_ALPHA_SIZE];
108
109 private int[] m_minLens = new int[N_GROUPS];
110
111 private boolean m_streamEnd;
112
113 private int m_currentChar = -1;
114
115 private int m_currentState = START_BLOCK_STATE;
116
117 private int m_rNToGo;
118
119 private int m_rTPos;
120
121 private int m_tPos;
122
123 private int i2;
124
125 private int count;
126
127 private int chPrev;
128
129 private int ch2;
130
131 private int j2;
132
133 private char z;
134
135 private boolean m_blockRandomised;
136
137
138
139
140
141 private int m_blockSize100k;
142
143 private int m_bsBuff;
144
145 private int m_bsLive;
146
147 private InputStream m_input;
148
149 private int m_computedBlockCRC;
150
151 private int m_computedCombinedCRC;
152
153
154
155
156 private int m_last;
157
158 private char[] m_ll8;
159
160 private int m_nInUse;
161
162
163
164
165 private int m_origPtr;
166
167 private int m_storedBlockCRC;
168
169 private int m_storedCombinedCRC;
170
171 private int[] m_tt;
172
173 public CBZip2InputStream(final InputStream input) {
174 bsSetStream(input);
175 initialize();
176 initBlock();
177 setupBlock();
178 }
179
180 private static void badBlockHeader() {
181 cadvise();
182 }
183
184 private static void blockOverrun() {
185 cadvise();
186 }
187
188 private static void cadvise() {
189 System.out.println("CRC Error");
190
191 }
192
193 private static void compressedStreamEOF() {
194 cadvise();
195 }
196
197 private static void crcError() {
198 cadvise();
199 }
200
201 public int read() {
202 if (m_streamEnd) {
203 return -1;
204 } else {
205 int retChar = m_currentChar;
206 switch (m_currentState) {
207 case START_BLOCK_STATE:
208 break;
209 case RAND_PART_A_STATE:
210 break;
211 case RAND_PART_B_STATE:
212 setupRandPartB();
213 break;
214 case RAND_PART_C_STATE:
215 setupRandPartC();
216 break;
217 case NO_RAND_PART_A_STATE:
218 break;
219 case NO_RAND_PART_B_STATE:
220 setupNoRandPartB();
221 break;
222 case NO_RAND_PART_C_STATE:
223 setupNoRandPartC();
224 break;
225 default:
226 break;
227 }
228 return retChar;
229 }
230 }
231
232 private void setDecompressStructureSizes(int newSize100k) {
233 if (!(0 <= newSize100k && newSize100k <= 9 && 0 <= m_blockSize100k && m_blockSize100k <= 9)) {
234
235 }
236
237 m_blockSize100k = newSize100k;
238
239 if (newSize100k == 0) {
240 return;
241 }
242
243 int n = BASE_BLOCK_SIZE * newSize100k;
244 m_ll8 = new char[n];
245 m_tt = new int[n];
246 }
247
248 private void setupBlock() {
249 int[] cftab = new int[257];
250 char ch;
251
252 cftab[0] = 0;
253 for (int i = 1; i <= 256; i++) {
254 cftab[i] = m_unzftab[i - 1];
255 }
256 for (int i = 1; i <= 256; i++) {
257 cftab[i] += cftab[i - 1];
258 }
259
260 for (int i = 0; i <= m_last; i++) {
261 ch = m_ll8[i];
262 m_tt[cftab[ch]] = i;
263 cftab[ch]++;
264 }
265 cftab = null;
266
267 m_tPos = m_tt[m_origPtr];
268
269 count = 0;
270 i2 = 0;
271 ch2 = 256;
272
273
274
275 if (m_blockRandomised) {
276 m_rNToGo = 0;
277 m_rTPos = 0;
278 setupRandPartA();
279 } else {
280 setupNoRandPartA();
281 }
282 }
283
284 private void setupNoRandPartA() {
285 if (i2 <= m_last) {
286 chPrev = ch2;
287 ch2 = m_ll8[m_tPos];
288 m_tPos = m_tt[m_tPos];
289 i2++;
290
291 m_currentChar = ch2;
292 m_currentState = NO_RAND_PART_B_STATE;
293 m_crc.updateCRC(ch2);
294 } else {
295 endBlock();
296 initBlock();
297 setupBlock();
298 }
299 }
300
301 private void setupNoRandPartB() {
302 if (ch2 != chPrev) {
303 m_currentState = NO_RAND_PART_A_STATE;
304 count = 1;
305 setupNoRandPartA();
306 } else {
307 count++;
308 if (count >= 4) {
309 z = m_ll8[m_tPos];
310 m_tPos = m_tt[m_tPos];
311 m_currentState = NO_RAND_PART_C_STATE;
312 j2 = 0;
313 setupNoRandPartC();
314 } else {
315 m_currentState = NO_RAND_PART_A_STATE;
316 setupNoRandPartA();
317 }
318 }
319 }
320
321 private void setupNoRandPartC() {
322 if (j2 < z) {
323 m_currentChar = ch2;
324 m_crc.updateCRC(ch2);
325 j2++;
326 } else {
327 m_currentState = NO_RAND_PART_A_STATE;
328 i2++;
329 count = 0;
330 setupNoRandPartA();
331 }
332 }
333
334 private void setupRandPartA() {
335 if (i2 <= m_last) {
336 chPrev = ch2;
337 ch2 = m_ll8[m_tPos];
338 m_tPos = m_tt[m_tPos];
339 if (m_rNToGo == 0) {
340 m_rNToGo = RAND_NUMS[m_rTPos];
341 m_rTPos++;
342 if (m_rTPos == 512) {
343 m_rTPos = 0;
344 }
345 }
346 m_rNToGo--;
347 ch2 ^= ((m_rNToGo == 1) ? 1 : 0);
348 i2++;
349
350 m_currentChar = ch2;
351 m_currentState = RAND_PART_B_STATE;
352 m_crc.updateCRC(ch2);
353 } else {
354 endBlock();
355 initBlock();
356 setupBlock();
357 }
358 }
359
360 private void setupRandPartB() {
361 if (ch2 != chPrev) {
362 m_currentState = RAND_PART_A_STATE;
363 count = 1;
364 setupRandPartA();
365 } else {
366 count++;
367 if (count >= 4) {
368 z = m_ll8[m_tPos];
369 m_tPos = m_tt[m_tPos];
370 if (m_rNToGo == 0) {
371 m_rNToGo = RAND_NUMS[m_rTPos];
372 m_rTPos++;
373 if (m_rTPos == 512) {
374 m_rTPos = 0;
375 }
376 }
377 m_rNToGo--;
378 z ^= ((m_rNToGo == 1) ? 1 : 0);
379 j2 = 0;
380 m_currentState = RAND_PART_C_STATE;
381 setupRandPartC();
382 } else {
383 m_currentState = RAND_PART_A_STATE;
384 setupRandPartA();
385 }
386 }
387 }
388
389 private void setupRandPartC() {
390 if (j2 < z) {
391 m_currentChar = ch2;
392 m_crc.updateCRC(ch2);
393 j2++;
394 } else {
395 m_currentState = RAND_PART_A_STATE;
396 i2++;
397 count = 0;
398 setupRandPartA();
399 }
400 }
401
402 private void getAndMoveToFrontDecode() {
403 int nextSym;
404
405 int limitLast = BASE_BLOCK_SIZE * m_blockSize100k;
406 m_origPtr = readVariableSizedInt(24);
407
408 recvDecodingTables();
409 int EOB = m_nInUse + 1;
410 int groupNo = -1;
411 int groupPos = 0;
412
413
414
415
416
417
418 for (int i = 0; i <= 255; i++) {
419 m_unzftab[i] = 0;
420 }
421
422 final char[] yy = new char[256];
423 for (int i = 0; i <= 255; i++) {
424 yy[i] = (char) i;
425 }
426
427 m_last = -1;
428 int zt;
429 int zn;
430 int zvec;
431 int zj;
432 groupNo++;
433 groupPos = G_SIZE - 1;
434
435 zt = m_selector[groupNo];
436 zn = m_minLens[zt];
437 zvec = bsR(zn);
438 while (zvec > m_limit[zt][zn]) {
439 zn++;
440
441 while (m_bsLive < 1) {
442 int zzi;
443 char thech = 0;
444 try {
445 thech = (char) m_input.read();
446 } catch (IOException e) {
447 compressedStreamEOF();
448 }
449 if (thech == -1) {
450 compressedStreamEOF();
451 }
452 zzi = thech;
453 m_bsBuff = (m_bsBuff << 8) | (zzi & 0xff);
454 m_bsLive += 8;
455 }
456
457 zj = (m_bsBuff >> (m_bsLive - 1)) & 1;
458 m_bsLive--;
459
460 zvec = (zvec << 1) | zj;
461 }
462 nextSym = m_perm[zt][zvec - m_base[zt][zn]];
463
464 while (true) {
465 if (nextSym == EOB) {
466 break;
467 }
468
469 if (nextSym == RUNA || nextSym == RUNB) {
470 char ch;
471 int s = -1;
472 int N = 1;
473 do {
474 if (nextSym == RUNA) {
475 s = s + (0 + 1) * N;
476 } else
477 {
478 s = s + (1 + 1) * N;
479 }
480 N = N * 2;
481
482 if (groupPos == 0) {
483 groupNo++;
484 groupPos = G_SIZE;
485 }
486 groupPos--;
487 zt = m_selector[groupNo];
488 zn = m_minLens[zt];
489 zvec = bsR(zn);
490 while (zvec > m_limit[zt][zn]) {
491 zn++;
492
493 while (m_bsLive < 1) {
494 int zzi;
495 char thech = 0;
496 try {
497 thech = (char) m_input.read();
498 } catch (IOException e) {
499 compressedStreamEOF();
500 }
501 if (thech == -1) {
502 compressedStreamEOF();
503 }
504 zzi = thech;
505 m_bsBuff = (m_bsBuff << 8) | (zzi & 0xff);
506 m_bsLive += 8;
507 }
508
509 zj = (m_bsBuff >> (m_bsLive - 1)) & 1;
510 m_bsLive--;
511 zvec = (zvec << 1) | zj;
512 }
513
514 nextSym = m_perm[zt][zvec - m_base[zt][zn]];
515
516 } while (nextSym == RUNA || nextSym == RUNB);
517
518 s++;
519 ch = m_seqToUnseq[yy[0]];
520 m_unzftab[ch] += s;
521
522 while (s > 0) {
523 m_last++;
524 m_ll8[m_last] = ch;
525 s--;
526 }
527
528 if (m_last >= limitLast) {
529 blockOverrun();
530 }
531 continue;
532 } else {
533 char tmp;
534 m_last++;
535 if (m_last >= limitLast) {
536 blockOverrun();
537 }
538
539 tmp = yy[nextSym - 1];
540 m_unzftab[m_seqToUnseq[tmp]]++;
541 m_ll8[m_last] = m_seqToUnseq[tmp];
542
543
544
545
546
547 int j = nextSym - 1;
548 for (; j > 3; j -= 4) {
549 yy[j] = yy[j - 1];
550 yy[j - 1] = yy[j - 2];
551 yy[j - 2] = yy[j - 3];
552 yy[j - 3] = yy[j - 4];
553 }
554 for (; j > 0; j--) {
555 yy[j] = yy[j - 1];
556 }
557
558 yy[0] = tmp;
559
560 if (groupPos == 0) {
561 groupNo++;
562 groupPos = G_SIZE;
563 }
564 groupPos--;
565 zt = m_selector[groupNo];
566 zn = m_minLens[zt];
567 zvec = bsR(zn);
568 while (zvec > m_limit[zt][zn]) {
569 zn++;
570
571 while (m_bsLive < 1) {
572 char ch = 0;
573 try {
574 ch = (char) m_input.read();
575 } catch (IOException e) {
576 compressedStreamEOF();
577 }
578
579 m_bsBuff = (m_bsBuff << 8) | (ch & 0xff);
580 m_bsLive += 8;
581 }
582
583 zj = (m_bsBuff >> (m_bsLive - 1)) & 1;
584 m_bsLive--;
585
586 zvec = (zvec << 1) | zj;
587 }
588 nextSym = m_perm[zt][zvec - m_base[zt][zn]];
589
590 continue;
591 }
592 }
593 }
594
595 private void bsFinishedWithStream() {
596 if (m_input != null) {
597 try {
598 m_input.close();
599 } catch (IOException e) {
600 }
601 }
602 m_input = null;
603 }
604
605 private int readVariableSizedInt(final int numBits) {
606 return bsR(numBits);
607 }
608
609 private char readUnsignedChar() {
610 return (char) bsR(8);
611 }
612
613 private int readInt() {
614 int u = 0;
615 u = (u << 8) | bsR(8);
616 u = (u << 8) | bsR(8);
617 u = (u << 8) | bsR(8);
618 u = (u << 8) | bsR(8);
619 return u;
620 }
621
622 private int bsR(final int n) {
623 while (m_bsLive < n) {
624 char ch = 0;
625 try {
626 ch = (char) m_input.read();
627 } catch (final IOException ioe) {
628 compressedStreamEOF();
629 }
630
631 if (ch == -1) {
632 compressedStreamEOF();
633 }
634
635 m_bsBuff = (m_bsBuff << 8) | (ch & 0xff);
636 m_bsLive += 8;
637 }
638
639 final int result = (m_bsBuff >> (m_bsLive - n)) & ((1 << n) - 1);
640 m_bsLive -= n;
641 return result;
642 }
643
644 private void bsSetStream(final InputStream input) {
645 m_input = input;
646 m_bsLive = 0;
647 m_bsBuff = 0;
648 }
649
650 private void complete() {
651 m_storedCombinedCRC = readInt();
652 if (m_storedCombinedCRC != m_computedCombinedCRC) {
653 crcError();
654 }
655
656 bsFinishedWithStream();
657 m_streamEnd = true;
658 }
659
660 private void endBlock() {
661 m_computedBlockCRC = m_crc.getFinalCRC();
662
663
664
665 if (m_storedBlockCRC != m_computedBlockCRC) {
666 crcError();
667 }
668
669 m_computedCombinedCRC = (m_computedCombinedCRC << 1)
670 | (m_computedCombinedCRC >>> 31);
671 m_computedCombinedCRC ^= m_computedBlockCRC;
672 }
673
674 private void hbCreateDecodeTables(final int[] limit, final int[] base,
675 final int[] perm, final char[] length, final int minLen,
676 final int maxLen, final int alphaSize) {
677 int pp = 0;
678 for (int i = minLen; i <= maxLen; i++) {
679 for (int j = 0; j < alphaSize; j++) {
680 if (length[j] == i) {
681 perm[pp] = j;
682 pp++;
683 }
684 }
685 }
686
687 for (int i = 0; i < MAX_CODE_LEN; i++) {
688 base[i] = 0;
689 }
690
691 for (int i = 0; i < alphaSize; i++) {
692 base[length[i] + 1]++;
693 }
694
695 for (int i = 1; i < MAX_CODE_LEN; i++) {
696 base[i] += base[i - 1];
697 }
698
699 for (int i = 0; i < MAX_CODE_LEN; i++) {
700 limit[i] = 0;
701 }
702
703 int vec = 0;
704 for (int i = minLen; i <= maxLen; i++) {
705 vec += (base[i + 1] - base[i]);
706 limit[i] = vec - 1;
707 vec <<= 1;
708 }
709
710 for (int i = minLen + 1; i <= maxLen; i++) {
711 base[i] = ((limit[i - 1] + 1) << 1) - base[i];
712 }
713 }
714
715 private void initBlock() {
716 final char magic1 = readUnsignedChar();
717 final char magic2 = readUnsignedChar();
718 final char magic3 = readUnsignedChar();
719 final char magic4 = readUnsignedChar();
720 final char magic5 = readUnsignedChar();
721 final char magic6 = readUnsignedChar();
722 if (magic1 == 0x17 && magic2 == 0x72 && magic3 == 0x45
723 && magic4 == 0x38 && magic5 == 0x50 && magic6 == 0x90) {
724 complete();
725 return;
726 }
727
728 if (magic1 != 0x31 || magic2 != 0x41 || magic3 != 0x59
729 || magic4 != 0x26 || magic5 != 0x53 || magic6 != 0x59) {
730 badBlockHeader();
731 m_streamEnd = true;
732 return;
733 }
734
735 m_storedBlockCRC = readInt();
736
737 if (bsR(1) == 1) {
738 m_blockRandomised = true;
739 } else {
740 m_blockRandomised = false;
741 }
742
743
744 getAndMoveToFrontDecode();
745
746 m_crc.initialiseCRC();
747 m_currentState = START_BLOCK_STATE;
748 }
749
750 private void initialize() {
751 char magic3 = readUnsignedChar();
752 char magic4 = readUnsignedChar();
753 if (magic3 == 'B' && magic4 == 'Z') {
754 magic3 = readUnsignedChar();
755 magic4 = readUnsignedChar();
756 }
757
758 if (magic3 != 'h' || magic4 < '1' || magic4 > '9') {
759 bsFinishedWithStream();
760 m_streamEnd = true;
761 return;
762 }
763
764 setDecompressStructureSizes(magic4 - '0');
765 m_computedCombinedCRC = 0;
766 }
767
768 private void makeMaps() {
769 m_nInUse = 0;
770 for (int i = 0; i < 256; i++) {
771 if (m_inUse[i]) {
772 m_seqToUnseq[m_nInUse] = (char) i;
773 m_unseqToSeq[i] = (char) m_nInUse;
774 m_nInUse++;
775 }
776 }
777 }
778
779 private void recvDecodingTables() {
780 buildInUseTable();
781 makeMaps();
782 final int alphaSize = m_nInUse + 2;
783
784
785
786
787 final int groupCount = bsR(3);
788 final int selectorCount = bsR(15);
789 for (int i = 0; i < selectorCount; i++) {
790 int run = 0;
791 while (bsR(1) == 1) {
792 run++;
793 }
794 m_selectorMtf[i] = (char) run;
795 }
796
797
798
799
800 final char[] pos = new char[N_GROUPS];
801 for (char v = 0; v < groupCount; v++) {
802 pos[v] = v;
803 }
804
805 for (int i = 0; i < selectorCount; i++) {
806 int v = m_selectorMtf[i];
807 final char tmp = pos[v];
808 while (v > 0) {
809 pos[v] = pos[v - 1];
810 v--;
811 }
812 pos[0] = tmp;
813 m_selector[i] = tmp;
814 }
815
816 final char[][] len = new char[N_GROUPS][MAX_ALPHA_SIZE];
817
818
819
820 for (int i = 0; i < groupCount; i++) {
821 int curr = bsR(5);
822 for (int j = 0; j < alphaSize; j++) {
823 while (bsR(1) == 1) {
824 if (bsR(1) == 0) {
825 curr++;
826 } else {
827 curr--;
828 }
829 }
830 len[i][j] = (char) curr;
831 }
832 }
833
834
835
836
837 for (int k = 0; k < groupCount; k++) {
838 int minLen = 32;
839 int maxLen = 0;
840 for (int i = 0; i < alphaSize; i++) {
841 if (len[k][i] > maxLen) {
842 maxLen = len[k][i];
843 }
844 if (len[k][i] < minLen) {
845 minLen = len[k][i];
846 }
847 }
848 hbCreateDecodeTables(m_limit[k], m_base[k], m_perm[k], len[k],
849 minLen, maxLen, alphaSize);
850 m_minLens[k] = minLen;
851 }
852 }
853
854 private void buildInUseTable() {
855 final boolean[] inUse16 = new boolean[16];
856
857
858
859
860 for (int i = 0; i < 16; i++) {
861 if (bsR(1) == 1) {
862 inUse16[i] = true;
863 } else {
864 inUse16[i] = false;
865 }
866 }
867
868 for (int i = 0; i < 256; i++) {
869 m_inUse[i] = false;
870 }
871
872 for (int i = 0; i < 16; i++) {
873 if (inUse16[i]) {
874 for (int j = 0; j < 16; j++) {
875 if (bsR(1) == 1) {
876 m_inUse[i * 16 + j] = true;
877 }
878 }
879 }
880 }
881 }
882
883 public void close() throws IOException {
884 bsFinishedWithStream();
885 }
886 }